home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1995 November
/
EnigmA AMIGA RUN 02 (1995)(G.R. Edizioni)(IT)[!][issue 1995-11][Skylink CD].iso
/
earcd
/
unix
/
mp14tar.z
/
mp14tar
/
mpack
/
macfile.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-06-01
|
8KB
|
256 lines
/* macfile.c -- simple applesingle/appledouble encoding/decoding routines
*
* (C) Copyright 1994 by Christopher J. Newman
* All Rights Reserved.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Christopher J. Newman not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Christopher J. Newman makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* CHRISTOPHER J. NEWMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
* SHALL CHRISTOPHER J. NEWMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#include <stdio.h>
#include <memory.h>
#include "macnapp.h" /* for NAfilterProc */
#include "macmpack.h" /* for copy_buf */
/* applefile definitions used */
#define APPLESINGLE_MAGIC 0x00051600L
#define APPLEDOUBLE_MAGIC 0x00051607L
#define VERSION 0x00020000
#define ENT_DFORK 1
#define ENT_RFORK 2
#define ENT_NAME 3
#define ENT_COMMENT 4
#define ENT_DATES 8
#define ENT_FINFO 9
#define CONVERT_TIME 1265437696L
/* applefile structures */
typedef struct ap_header {
long magic;
long version;
char fill[16];
short entries;
} ap_header;
typedef struct ap_entry {
unsigned long id;
unsigned long offset;
unsigned long length;
} ap_entry;
typedef struct ap_dates {
long create, modify, backup, access;
} ap_dates;
/* default number of entries */
#define NUM_ENTRIES 6
/* Generate an applefile
* outfile -- output file
* fpb -- hierarchical file parameter block
* rfork, dfork -- resource & data forks
* returns -1 on failure, 0 on success
*
* closes dfork & rfork, but not outputfile
*/
int encode_applefile(FILE *outfile, HFileInfo *fpb, FILE *rfork, FILE *dfork)
{
ap_header head;
ap_entry entries[NUM_ENTRIES];
ap_dates dates;
short i, count;
DateTimeRec cur_time;
unsigned long cur_secs;
/* make sure things look OK */
if (!rfork || !outfile) {
if (rfork) fclose(rfork);
if (dfork) fclose(dfork);
if (outfile) fclose(outfile);
return (-1);
}
/* write header */
head.magic = dfork ? APPLESINGLE_MAGIC : APPLEDOUBLE_MAGIC;
head.version = VERSION;
memset(head.fill, '\0', sizeof (head.fill));
head.entries = NUM_ENTRIES - (dfork ? 0 : 1);
fwrite((char *) &head, sizeof (head), 1, outfile);
/* write entry descriptors */
entries[0].offset = sizeof (head) + sizeof (ap_entry) * head.entries;
entries[0].id = ENT_NAME;
entries[0].length = *fpb->ioNamePtr;
entries[1].id = ENT_FINFO;
entries[1].length = sizeof (FInfo) + sizeof (FXInfo);
entries[2].id = ENT_DATES;
entries[2].length = sizeof (ap_dates);
entries[3].id = ENT_COMMENT;
entries[3].length = 0;
entries[4].id = ENT_RFORK;
entries[4].length = fpb->ioFlRLgLen;
entries[5].id = ENT_DFORK;
entries[5].length = fpb->ioFlLgLen;
for (i = 1; i < NUM_ENTRIES; ++i) {
entries[i].offset = entries[i-1].offset + entries[i-1].length;
}
fwrite((char *) entries, sizeof (ap_entry), head.entries, outfile);
/* write name */
fwrite((char *) fpb->ioNamePtr + 1, *fpb->ioNamePtr, 1, outfile);
/* write finder info */
fwrite((char *) &fpb->ioFlFndrInfo, sizeof (FInfo), 1, outfile);
fwrite((char *) &fpb->ioFlXFndrInfo, sizeof (FXInfo), 1, outfile);
/* write dates */
GetTime(&cur_time);
Date2Secs(&cur_time, &cur_secs);
dates.create = fpb->ioFlCrDat + CONVERT_TIME;
dates.modify = fpb->ioFlMdDat + CONVERT_TIME;
dates.backup = fpb->ioFlBkDat + CONVERT_TIME;
dates.access = cur_secs + CONVERT_TIME;
fwrite((char *) &dates, sizeof (ap_dates), 1, outfile);
/*XXX: need to write comment */
/* write resource fork */
while ((count = fread(copy_buf, sizeof (char), sizeof (copy_buf), rfork)) > 0) {
fwrite(copy_buf, sizeof (char), count, outfile);
}
fclose(rfork);
/* write data fork */
if (dfork) {
while ((count = fread(copy_buf, sizeof (char), sizeof (copy_buf), dfork)) > 0) {
fwrite(copy_buf, sizeof (char), count, outfile);
}
fclose(dfork);
}
return (0);
}
/* decode an applefile
* infile -- input file
* fspec -- file spec of saved file
* returns -1 on failure, 0 on success
*/
int decode_applefile(FILE *infile, FSSpec *fspec)
{
ap_header head;
ap_entry entries[NUM_ENTRIES + 1];
ap_dates dates;
Point where;
SFReply reply;
int i, j;
short refnum;
long count;
OSErr err;
HFileInfo *fpb;
CInfoPBRec cipbr;
/* read & verify header */
fread((char *) &head, sizeof (head), 1, infile);
if (head.magic != APPLESINGLE_MAGIC && head.magic != APPLEDOUBLE_MAGIC) {
return (-1);
}
if (head.version != VERSION) {
return (-1);
}
/* read entries */
for (i = j = 0; i < head.entries; ++i) {
fread((char *) (entries + j), sizeof (ap_entry), 1, infile);
if (j < NUM_ENTRIES) switch (entries[j].id) {
case ENT_NAME:
case ENT_FINFO:
case ENT_DATES:
case ENT_COMMENT:
case ENT_RFORK:
case ENT_DFORK:
++j;
break;
}
}
/* read name */
for (i = 0; i < j && entries[i].id != ENT_NAME; ++i);
if (i == j) return (-1);
fseek(infile, entries[i].offset, SEEK_SET);
if (entries[i].length > 63) entries[i].length = 63;
*fspec->name = fread((char *) fspec->name + 1, sizeof (char), entries[i].length, infile);
where.h = where.v = 0;
SFPutFile(where, "\pSave decoded file as:", fspec->name, NULL, &reply);
if (!reply.good) return (-1);
BlockMove(reply.fName, fspec->name, sizeof (fspec->name));
fspec->vRefNum = reply.vRefNum;
fspec->parID = 0;
/* create & get info for file */
if (Create(fspec->name, fspec->vRefNum, '????', '????') != noErr) return (-1);
fpb = (HFileInfo *) &cipbr;
fpb->ioVRefNum = fspec->vRefNum;
fpb->ioNamePtr = fspec->name;
fpb->ioDirID = 0;
fpb->ioFDirIndex = 0;
PBGetCatInfoSync(&cipbr);
/* get finder info */
for (i = 0; i < j && entries[i].id != ENT_FINFO; ++i);
if (i < j) {
fseek(infile, entries[i].offset, SEEK_SET);
fread((char *) &fpb->ioFlFndrInfo, sizeof (FInfo), 1, infile);
fread((char *) &fpb->ioFlXFndrInfo, sizeof (FXInfo), 1, infile);
fpb->ioFlFndrInfo.fdFlags &= 0xf800; /* clear flags maintained by finder */
}
/* get file date info */
for (i = 0; i < j && entries[i].id != ENT_DATES; ++i);
if (i < j) {
fseek(infile, entries[i].offset, SEEK_SET);
fread((char *) &dates, sizeof (dates), 1, infile);
fpb->ioFlCrDat = dates.create - CONVERT_TIME;
fpb->ioFlMdDat = dates.modify - CONVERT_TIME;
fpb->ioFlBkDat = dates.backup - CONVERT_TIME;
}
/* update info */
fpb->ioDirID = 0;
PBSetCatInfo(&cipbr, FALSE);
/* do resource/data forks */
for (i = 0; i < j; ++i) {
if (entries[i].id == ENT_RFORK || entries[i].id == ENT_DFORK) {
fseek(infile, entries[i].offset, SEEK_SET);
if (entries[i].id == ENT_DFORK) {
err = HOpen(fspec->vRefNum, fspec->parID, fspec->name, 2, &refnum);
} else {
err = HOpenRF(fspec->vRefNum, fspec->parID, fspec->name, 2, &refnum);
}
if (err != noErr) {
FSDelete(fspec->name, fspec->vRefNum);
return (-1);
}
while (entries[i].length > sizeof (copy_buf)) {
count = fread(copy_buf, sizeof (char), sizeof (copy_buf), infile);
entries[i].length -= count;
FSWrite(refnum, &count, (Ptr) copy_buf);
}
count = fread(copy_buf, sizeof (char), entries[i].length, infile);
FSWrite(refnum, &count, (Ptr) copy_buf);
FSClose(refnum);
}
}
return (0);
}